﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using Emgu.CV.UI;
using Emgu.CV.Structure;
using Emgu.CV;
using System.Drawing;
using AsyncCamera.Camera.Structure;
using Incendios0_1.Camera.wpfdatamanager;
using AsyncCamera.Camera.media;
using Incendios0_1.Camera;

namespace AsyncCamera.Camera
{
    public class OpenCVImageBoxSink: MediaSink
    {
        private LinkedImageBox<AbstractCamera> display;
        public LinkedImageBox<AbstractCamera> Display
        {
            get
            {
                return display;
            }
        }

        private CameraSink displayBox;
        public CameraSink DisplayBox
        {
            get
            {
                return displayBox;
            }

            set
            {
                this.displayBox = value;
                this.display = value.Display;
            }
        }

        private Guid sourceId;

        public OpenCVImageBoxSink()
            : base()
        {
        }

        public OpenCVImageBoxSink(MediaSource source, CameraSink displayBox)
            : base()
        {
            sourceId = source.GUID;
            plugIn[sourceId] = source;
            lastFrame[sourceId] = source.Frame;
            this.displayBox = displayBox;
            this.display = displayBox.Display;
        }

        public OpenCVImageBoxSink(MediaSource source)
            : base()
        {
            sourceId = source.GUID;
            plugIn[sourceId] = source;
            lastFrame[sourceId] = source.Frame;
            this.displayBox = null;
            this.display = null;
        }

        public override void plugSource(MediaSource newPlugIn)
        {
            setSource(newPlugIn);
        }

        public void setSource(MediaSource src)
        {
            if (plugIn.Count > 0)
            {
                plugIn.Remove(sourceId);
                lastFrame.Remove(sourceId);
            }
            sourceId = src.GUID;
            plugIn[sourceId] = src;
            lastFrame[sourceId] = src.Frame;
        }

        protected override void Tick(object sender, EventArgs e)
        {
            if (plugIn.Count > 0)
            {
                Frame newFrame = plugIn[sourceId].Frame;
                if (newFrame != null && (lastFrame[sourceId] == null || lastFrame[sourceId].Id != newFrame.Id))
                {
                    lastFrame[sourceId] = newFrame;
                    if (lastFrame[sourceId].Error == MediaError.OK)
                    {
                        try
                        {
                            displayBox.Dispatcher.Invoke(
                            System.Windows.Threading.DispatcherPriority.Normal,
                            new Action(
                                delegate()
                                {
                                    if (display != null)
                                    {
                                        displayBox.Image = lastFrame[sourceId].Image.Clone() as Emgu.CV.Image<Bgr, Byte>;
                                        display.Update();
                                    }
                                }
                            ));
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                    else
                    {
                        displayBox.Dispatcher.Invoke(
                            System.Windows.Threading.DispatcherPriority.Normal,
                            new Action(
                                delegate()
                                {
                                    Image<Bgr, Byte> img;
                                    if (lastFrame[sourceId].Image != null)
                                        img = lastFrame[sourceId].Image.Clone() as Emgu.CV.Image<Bgr, Byte>;
                                    else
                                        img = new Image<Bgr, Byte>(320, 240, new Bgr(255, 255, 255));
                                    MCvFont f = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_COMPLEX, 0.3, 0.3);
                                    img.Draw(newFrame.Message, ref f, new Point(25, 100), new Bgr(0, 0, 0));
                                    if (display != null)
                                        display.Image = img;
                                }
                            ));
                    }
                }
            }
        }
    }
}
